﻿using System.Collections.Generic;
using System.Data;
using System.Linq;
using viBook.Common;
using viBook.Models;

namespace viBook.Repositories
{
    public class AuthorRepository : IAuthorRepository
    {
        private readonly viBookContext _context = new viBookContext();

        #region IAuthorRepository Members

        public IQueryable<Author> All
        {
            get
            {
                IQueryable<Author> result = _context.Authors;
                foreach (var author in result)
                {
                    author.NumberOfBook = _context.Books.Where(b => b.AuthorId == author.Id).Count();
                }
                return result;
            }
        }

        public Author Find(int id)
        {
            return _context.Authors.Find(id);
        }

        public void InsertOrUpdate(Author author)
        {
            if (author.Id == default(int))
            {
                _context.Authors.Add(author);
            }
            else
            {
                _context.Entry(author).State = EntityState.Modified;
            }
            Save();
        }

        public void Delete(int id)
        {
            Author author = _context.Authors.Find(id);
            if (author != null)
                _context.Authors.Remove(author);
            Save();
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public IEnumerable<string> FindAuthors(string criteria, int limit)
        {
            return _context.Authors.
                Where(c => c.AuthorName.ToLower().Contains(criteria.ToLower())).
                Take(limit).
                Select(c => c.AuthorName);
        }

        public int FindAuthorId(string authorName)
        {
            Author author = _context.Authors.
                Where(c => c.AuthorName.ToLower().Equals(authorName.ToLower())).FirstOrDefault();
            if (author != null)
                return author.Id;
            var autho = new Author {AuthorName = authorName};
            InsertOrUpdate(autho);
            Save();
            return autho.Id;
        }

        public Author FindAuthorWithAllBooks(int id)
        {
            Author author = _context.Authors.Find(id);
            if (author != null)
            {
                List<Book> listBook =
                    _context.Books.Where(b => b.AuthorId == author.Id && b.IsBlocked==false).OrderByDescending(b => b.NumberOfViews).ToList();
                foreach (Book book in listBook)
                {
                    GetBookDetailInformation(book);
                }
                author.ListBook = listBook;
            }
            return author;
        }


        public IEnumerable<Book> FetchNextBookPage(int authorId, int pageNumber)
        {
            int skipItem = (pageNumber - 1)*Constant.MaximunItemsToPaging;
            List<Book> listBook =
                _context.Books.Where(b => b.AuthorId == authorId)
                    .OrderByDescending(p => p.NumberOfViews)
                    .Skip(skipItem)
                    .Take(Constant.MaximunItemsToPaging).ToList();
            foreach (Book book in listBook)
            {
                GetBookDetailInformation(book);
            }
            return listBook;
        }

        #endregion

        private void GetBookDetailInformation(Book book)
        {
            if (book == null) return;
            book.NumberOfLikes = _context.BookLikes.Where(bl => bl.BookId == book.Id).ToList().Count();
            book.NumberOfComments = _context.BookComments.Where(bc => bc.BookId == book.Id).ToList().Count();

            book.Uploader = _context.Users.Where(u => u.Id == book.UploadedBy).FirstOrDefault();
            if (book.Uploader != null)
            {
                book.UploaderName = book.Uploader.DisplayName;
                book.UploaderAvartar = book.Uploader.AvatarUrl;
            }
        }
    }

    #region Nested type: IAuthorRepository

    public interface IAuthorRepository
    {
        IQueryable<Author> All { get; }
        Author Find(int id);
        void InsertOrUpdate(Author author);
        void Delete(int id);
        void Save();
        IEnumerable<string> FindAuthors(string criteria, int limit);
        int FindAuthorId(string authorName);
        Author FindAuthorWithAllBooks(int id);
        IEnumerable<Book> FetchNextBookPage(int authorId, int pageNumber);
    }

    #endregion
}
